www.gusucode.com > VC++ RingSDK界面库 > VC++ RingSDK界面库/code/libsrc/ringdows/ringlistview.cpp

    /**********************************************************************
//
//
//        ##########                          ######  #########   # ######    #
//      #############                      ########### ######### #########  ###
//     ######## # ###  ##                 ############# ##    ## #####  # ####
//     ####  ##    ## ###                 ###     ### # #      #####   #####
//          #     ###  #            #     ##       ##  ##      ##     ###
//         ## ###### ##      ##  ####    ####          #       #     ##
//       #########  ###  ## ### #######   ######      ##      ##    ###
//      ######      ##  ######  ##  ##       ####     #      ##     ####
//     #######     ##   ###### ##  ###          ##   ##     ###    ######
//     #########   ##  ###### ## ######         ### ##    ###      #  #####
//    ##    ###### ####### ### #### ##  ## #######  ########      ##    ####
//    ##      #### ###  #  ### ### ##  ##########   ######       ##      ####
//   ##         ##                ##   #########    ####         #         ##
//               #              ###
//                              ##
//                             ###
//                             ##
//
//
//							临风程序界面类库 ringdows.lib
//作者:临风
//
//版本:1.0
//
//声明:本类库可以自由使用而不须对作者作出任何回报,但作者希望能得到
//		  你的鼓励和支持。你可以对类库源码作出修改和改进,但希望你能在
//		  修改的同时给作者一份同样的副本。
//		  本类库不得用于任何商业用途,如确实需要,请与作者联系。
//
//e-mail:ringphone@sina.com
//
//原文件名:ringlistview.cpp
//
//说明:listview控件控制
//
**********************************************************************/
#define MAKE_SELF_LIB
#include "ringdows.h"

RingListView::RingListView()
{
	m_hImageBig = m_hImageSmall = m_hImageState = NULL;
	m_dwImgFreeMask = 0;
	m_header = NULL;
	m_windowType = ITIS_LISTVIEW;
}

RingListView::~RingListView()
{
	if(m_hImageBig)
		ImageList_Destroy(m_hImageBig);		
	if(m_hImageSmall)
		ImageList_Destroy(m_hImageSmall);
	if(m_hImageState)
		ImageList_Destroy(m_hImageState);
}

BOOL RingListView::Create(DWORD dwStyle,DWORD dwExStyle,LPCTSTR szInitText,UINT uId,int x,int y,int width,int height)
{   
	InitCommonControls();
	
	RingControls::Create(dwStyle,dwExStyle,szInitText,uId,x,y,width,height);
		
	//InitImageList();
   return (BOOL)m_hWnd;
}

void RingListView::SetExStyle(DWORD dwExStyle)
{
	if(dwExStyle != 0 && m_hWnd)
	{
		//ListView专有扩展属性必须用以下方法设置,
		DWORD dwStyle = SendMessage(m_hWnd,LVM_GETEXTENDEDLISTVIEWSTYLE,0,0);
		dwStyle |= dwExStyle;
		SendMessage(m_hWnd,LVM_SETEXTENDEDLISTVIEWSTYLE,0,dwStyle);
	}
}

LRESULT RingListView::DefaultProc(RINGPARAMS& param)
{
	if(param.uMsg == WM_NCDESTROY)
	{
		//BoundCheck的奇怪BUG:窗口过程销毁了IMAGELIST,析构时调用
		//ImageList_Destroy出错,BoundCheck报资源泄漏。
		//为避免该信息,这里检测如果是内置的就把ImageList设置为空
		if(ListView_GetImageList(m_hWnd,LVSIL_NORMAL) == m_hImageBig)
			ListView_SetImageList(m_hWnd,NULL,LVSIL_NORMAL);
		if(ListView_GetImageList(m_hWnd,LVSIL_SMALL) == m_hImageSmall)
			ListView_SetImageList(m_hWnd,NULL,LVSIL_SMALL);
		if(ListView_GetImageList(m_hWnd,LVSIL_STATE) == m_hImageState)
			ListView_SetImageList(m_hWnd,NULL,LVSIL_STATE);
		CallWindowProc(m_DefProc,m_hWnd,param.uMsg,param.wParam,param.lParam);
		OnNcDestroy();
		return 0;
	}	
	return CallWindowProc(m_DefProc,m_hWnd,param.uMsg,param.wParam,param.lParam);
}

//创建IMAGELIST,如不需要可设为0
void RingListView::InitImageList(int nBigX,int nBigY,
											int nSmallX,int nSmallY,
											int nStateX,int nStateY)
{
	if(m_hImageBig == NULL && (nBigX != 0 && nBigY != 0))
	{
		m_hImageBig = ImageList_Create(nBigX,nBigY,ILC_COLOR32|ILC_MASK,5,5);
		if(m_hWnd && m_hImageBig && ListView_GetImageList(m_hWnd,LVSIL_NORMAL) == NULL)
			ListView_SetImageList(m_hWnd,m_hImageBig,LVSIL_NORMAL);
	}	
	if(m_hImageSmall == NULL && (nSmallX != 0 && nSmallY != 0))
	{
		m_hImageSmall = ImageList_Create(nSmallX,nSmallY,ILC_COLOR32|ILC_MASK,5,5);
		if(m_hWnd && m_hImageSmall && ListView_GetImageList(m_hWnd,LVSIL_SMALL) == NULL)
			ListView_SetImageList(m_hWnd,m_hImageSmall,LVSIL_SMALL);
	}
	if(m_hImageState == NULL && (nStateX != 0 && nStateY != 0))
	{
		m_hImageState = ImageList_Create(nStateX,nStateY,ILC_COLOR32|ILC_MASK,5,5);
		if(m_hWnd && m_hImageState && ListView_GetImageList(m_hWnd,LVSIL_STATE) == NULL)
			ListView_SetImageList(m_hWnd,m_hImageState,LVSIL_STATE);
	}
}

////////////////////////////////////////////////////
//
//添加图标,必须已设置过IMAGELIST或调用过InitImageList(),
//如果图标包含不同尺寸,分别把最匹配尺寸图标添加到相应的
//IMAGELIST中。
//
//返回:最大的图标序号
//
////////////////////////////////////////////////////
int RingListView::AddIcon(LPCTSTR lpszIcon,HINSTANCE hInst/*=GetInstance()*/)
{
	//因为有可能调用过SetImageList,因此不能使用内置的m_hImageXXX,
	//必须ListView_GetImageList
	HIMAGELIST himl = ListView_GetImageList(m_hWnd,LVSIL_NORMAL);
	HICON hicon;
	int x,y;
	int nIndex = -1;

	if(himl)
	{
		if(!ImageList_GetIconSize(himl,&x,&y))
			x = y = 32;
			
		hicon = (HICON)LoadImage(hInst,lpszIcon,IMAGE_ICON,x,y,LR_DEFAULTCOLOR);
		if(hicon)
			nIndex = ImageList_AddIcon(himl,hicon);
	}
	
	himl = ListView_GetImageList(m_hWnd,LVSIL_SMALL);
	if(himl)
	{
		if(!ImageList_GetIconSize(himl,&x,&y))
			x = y = 16;
		
		hicon = (HICON)LoadImage(hInst,lpszIcon,IMAGE_ICON,x,y,LR_DEFAULTCOLOR);
		if(hicon)
			nIndex = max(nIndex,ImageList_AddIcon(himl,hicon));
	}
	return nIndex;
}

int RingListView::AddIcon(UINT uidIcon,HINSTANCE hInst/*=GetInstance()*/)
{
	return AddIcon(MAKEINTRESOURCE(uidIcon),hInst);
}

//添加图标,同时添加到大小图标列表中,返回最大的图标序号
int RingListView::AddIcon(HICON hicon)
{
	if(hicon == NULL)
		return -1;

	int nIndex = -1;
	HIMAGELIST himl = ListView_GetImageList(m_hWnd,LVSIL_NORMAL);
	if(himl)
		nIndex = ImageList_AddIcon(himl,hicon);
	
	himl = ListView_GetImageList(m_hWnd,LVSIL_SMALL);
	if(himl)
		nIndex = max(nIndex,ImageList_AddIcon(himl,hicon));

	return nIndex;
}

////////////////////////////////////////////////////
//
//添加图标,必须已设置过IMAGELIST或调用过InitImageList(),
//如果图标包含不同尺寸,把最匹配尺寸图标添加到相应的
//IMAGELIST中。
//
//返回:图标序号
//
////////////////////////////////////////////////////
int RingListView::AddIcon(UINT uidIcon,UINT uFlag,HINSTANCE hInst/*=GetInstance()*/)
{
	HICON hicon;
	HIMAGELIST himl = ListView_GetImageList(m_hWnd,uFlag);
	int x,y;
	
	if(himl)
	{
		if(ImageList_GetIconSize(himl,&x,&y))
			hicon = (HICON)LoadImage(hInst,MAKEINTRESOURCE(uidIcon),IMAGE_ICON,x,y,LR_DEFAULTCOLOR);
		else
			hicon = LoadIcon(hInst,MAKEINTRESOURCE(uidIcon));
		
		if(hicon)
			return ImageList_AddIcon(himl,hicon);
	}
	return -1;	
}

//uFlag:LVSIL_NORMAL,LVSIL_SMALL,LVSIL_STATE
int RingListView::AddIcon(HICON hicon,UINT uFlag)
{
	HIMAGELIST himl = ListView_GetImageList(m_hWnd,uFlag);
	
	if(hicon == NULL || himl == NULL)
		return -1;

	return ImageList_AddIcon(himl,hicon);	
}

LONG RingListView::GetData(int index)
{
	LVITEM lvt;
	lvt.mask = LVIF_PARAM;
	lvt.iItem = index;
	lvt.iSubItem = 0;
	lvt.lParam = 0;

	if(ListView_GetItem(m_hWnd,&lvt))
		return lvt.lParam;
	else
		return 0;
}

BOOL RingListView::SetData(int index,LONG lParam)
{
	LVITEM lvt;
	lvt.mask = LVIF_PARAM;
	lvt.iItem = index;
	lvt.iSubItem = 0;
	lvt.lParam = lParam;
	
	return ListView_SetItem(m_hWnd,&lvt);
}

int RingListView::SetColumns(LPCTSTR szColumn)
{
	if(m_hWnd == NULL || szColumn == NULL)
		return 0;

	ClearColumn();

	LV_COLUMN lvc; 
	int i,c = 0;
	ringStr str;
	LPTSTR s;
	int iCol,iWidth;

	str = szColumn;
	iCol = str.count("|") + 1;
	iWidth = (Width() - GetSystemMetrics(SM_CXVSCROLL))/iCol;

		// Initialize the LV_COLUMN structure. 
	lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
	lvc.fmt = LVCFMT_LEFT; 
		
	// Add the columns. 
	for(i=0;i<iCol;i++) 
	{ 
		lvc.iSubItem = i;
		s = (LPTSTR)str.string() + c;
		c = str.indexOf("|",c);
		str[c] = '\0';
		
		lvc.cx = iWidth;
		lvc.pszText = s;
			
		if(ListView_InsertColumn(m_hWnd,i,&lvc) == -1) 
		{
			str[c] = '|';
			return i;
		}
		str[c++] = '|';
	}
	return iCol;
}

BOOL RingListView::SetColumnsWidth(LPCTSTR szWidth)
{
	if(m_hWnd == NULL || szWidth == NULL)
		return FALSE;
	
	int i,c = 0;
	ringStr str;
	LPTSTR s;
	int iCol,iWidth;
	
	str = szWidth;
	iCol = str.count("|") + 1;
	
	for(i=0;i<iCol;i++) 
	{ 
		s = (LPTSTR)str.string() + c;
		c = str.indexOf("|",c);
		if(str[c-1] == '\\')
		{
			c++;
			continue;
		}
		str[c] = '\0';
		iWidth = atoi(s);
		
		if(!ListView_SetColumnWidth(m_hWnd,i,iWidth))
		{
			str[c] = '|';
			return FALSE;
		}
		str[c++] = '|';
	}	
	return TRUE; 
}

BOOL RingListView::InsertColumn(LPCTSTR szColumn,int subindex,int width,UINT uAlign/*=LVCFMT_LEFT*/,UINT uidIcon/*=0*/)
{
	if(m_hWnd == NULL || szColumn == NULL)
		return FALSE;
	
	LV_COLUMN lvc; 
	int iconId = -1;

	if(uidIcon != 0)
	{
		iconId = AddIcon(uidIcon);
		lvc.mask = LVCF_IMAGE;
	}
	else
		lvc.mask = 0;

	// Initialize the LV_COLUMN structure. 
	lvc.mask |= LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
	lvc.fmt = uAlign;
	lvc.cx = width;
	lvc.iSubItem = subindex;
	lvc.iImage = iconId;
	lvc.pszText = (LPSTR)szColumn;
			
	return (ListView_InsertColumn(m_hWnd,subindex,&lvc) != -1);
}

int RingListView::InsertRow(int index)
{
	LV_ITEM lvi;
	
	lvi.mask = LVIF_TEXT | LVIF_STATE;
	lvi.state = LVIS_FOCUSED | LVIS_SELECTED;
	lvi.stateMask = 0;
	lvi.pszText = "";
	lvi.cchTextMax = 300;
	
	lvi.iItem = index;
	lvi.iSubItem = 0; 
	
	return ListView_InsertItem(m_hWnd,&lvi);
}

int RingListView::AddRow()
{
	return InsertRow(GetCount());
}

int RingListView::AddItem(int index,LPCTSTR szText,LPARAM lParam,int idIcon)
{
	LV_ITEM lvi; 
	lvi.mask = 0;
	
	if(idIcon >= 0)
	{
		lvi.mask = LVIF_IMAGE;
		lvi.iImage = idIcon;
	}
	
	lvi.state = 0;
	lvi.stateMask = 0;
	
	if(szText)
	{
		lvi.mask |= TVIF_TEXT;
		lvi.pszText = (LPSTR)szText;
		lvi.cchTextMax = strlen(szText);
	}
	
	lvi.iItem = index; 
	lvi.iSubItem = 0;
	
	lvi.mask |= LVIF_PARAM;
	lvi.lParam = lParam;
	return ListView_InsertItem(m_hWnd,&lvi);	
}

int RingListView::SetItem(int index,int subindex,LPCTSTR szText,LPARAM lParam,int idIcon)
{
	LV_ITEM lvi; 
	lvi.mask = 0;

	if(idIcon >= 0)
	{
		lvi.mask = LVIF_IMAGE;
		lvi.iImage = idIcon;
	}
	
	lvi.state = 0;
	lvi.stateMask = 0;
	
	if(szText)
	{
		lvi.mask |= TVIF_TEXT;
		lvi.pszText = (LPSTR)szText;
		lvi.cchTextMax = strlen(szText);
	}
	
	lvi.iItem = index; 
	lvi.iSubItem = subindex;
	
	return ListView_SetItem(m_hWnd,&lvi)?index:-1;
} 

int RingListView::AddItem(int index,int nVal,LPARAM lParam,int uiconId)
{
	char s[16];
	wsprintf(s,"%d\0",nVal);
	return AddItem(index,s,lParam,uiconId);
}

int RingListView::SetItem(int index,int subindex,int nVal,LPARAM lParam,int uiconId)
{
	char s[16];
	wsprintf(s,"%d\0",nVal);
	return SetItem(index,subindex,s,lParam,uiconId);
}

BOOL RingListView::SetViewOf(UINT uType)
{
	LONG dNotView = ~(LVS_ICON|LVS_SMALLICON|LVS_LIST|LVS_REPORT);
	return SetWindowLong(m_hWnd,GWL_STYLE,GetWindowLong(m_hWnd,GWL_STYLE)&dNotView|uType);
}

LPCTSTR RingListView::GetText(int index,int subIndex,int size/*=RBUF_SIZE*/,LPSTR lpBuf/*=NULL*/)
{
   if(lpBuf == NULL)
	{
		if(GetBuffer(size))
		{
			memset(m_buf,0,m_bufsize);
			ListView_GetItemText(m_hWnd,index,subIndex,m_buf,m_bufsize);
			return m_buf;
		}
		else
			return "";
	}
	else
	{
		memset(lpBuf,0,size);
		ListView_GetItemText(m_hWnd,index,subIndex,lpBuf,size);
		return lpBuf;
	}
}

//重载的虚函数,获取第一列的文本
int RingListView::GetItemText(int index,LPTSTR lpBuf,int size)
{
	if(index == INDEX_CURSEL)
	{
		index = GetCurSel();
		if(index == -1)
			return 0;
	}
	
	LV_ITEM lv;
	lv.pszText = lpBuf;
	lv.cchTextMax = size;
	lv.iSubItem = 0;
	return SendMessage(m_hWnd,LVM_GETITEMTEXT,index,(LPARAM)&lv);
}

int RingListView::HitTest(int x,int y,LPLVHITTESTINFO lpvInfo/*=NULL*/)
{
	LVHITTESTINFO lpv;
	if(lpvInfo == NULL)
		lpvInfo = &lpv;

	lpvInfo->pt.x = x;
	lpvInfo->pt.y = y;

	return ListView_HitTest(m_hWnd,lpvInfo);
}

int RingListView::FindString(LPCTSTR szFind,int nStart/*=-1*/)
{
	LVFINDINFO lvf;

	lvf.flags = LVFI_PARTIAL;
	lvf.psz = szFind;

	return ListView_FindItem(m_hWnd,nStart,&lvf);
}

int RingListView::FindMatchString(LPCTSTR szFind,int nStart/*=-1*/)
{
	LVFINDINFO lvf;
	
	lvf.flags = LVFI_STRING;
	lvf.psz = szFind;
	
	return ListView_FindItem(m_hWnd,nStart,&lvf);
}

BOOL RingListView::SetValue(int val,int index/*=INDEX_CURSEL*/)
{
	char szText[16];
	wsprintf(szText,"%d\0",val);
	return SetValue(szText,index);
}

BOOL RingListView::SetValue(LPCTSTR lpszVal,int index/*=INDEX_CURSEL*/)
{
	if(lpszVal == NULL)
		return FALSE;

	if(index == INDEX_CURSEL)
	{
		index = GetCurSel();
		if(index == -1)
			return FALSE;
	}
	
	LV_ITEM lv;
	lv.pszText = (LPSTR)lpszVal;
	lv.iSubItem = 0;
	return SendMessage(m_hWnd,LVM_SETITEMTEXT,index,(LPARAM)&lv);
}

RingHeader* RingListView::GetHeaderObj()
{
	if(m_header == NULL)
	{
		HWND hWnd = GetHeader();
		if(hWnd)
		{
			m_header = (RingHeader*)GetWindowPtr(hWnd);

			if(m_header == NULL)
			{
				m_header = NewRingObj(itemof(RingHeader));
				m_header->Attach(hWnd);
			}
		}
	}
	return m_header;
}

HIMAGELIST RingListView::GetColumnImageList()
{
	if(GetHeaderObj())
		return m_header->GetImageList();
	else
		return NULL;
}

HIMAGELIST RingListView::SetColumnImageList(HIMAGELIST hImage,int cx,int cy)
{
	if(GetHeaderObj())
	{
		if(hImage == NULL)
		{
			//ListView如果设置了IMAGELIST,则列头的IMAGELIST已设置过
			//如果listview用做文件列表采用系统文件IMAGELIST,则列头需要
			//设置自己的IMAGELIST,否则只能使用系统文件IMAGELIST里的图标
			//且不能自己添加图标,(如果添加会影响Listview里正常的图标)
			hImage = m_header->GetImageList();
			//列头类设计成如果其m_hImage为空,则创建并设置IMAGELIST为m_hImage
			m_header->InitImageList(cx,cy);
			return hImage;
		}
		else
			return m_header->SetImageList(hImage);
	}
	return NULL;
}

BOOL RingListView::SetColumnImage(int nIndex,int nIconId,BOOL bOnRight)
{
	LVCOLUMN lvc;
	
	lvc.mask = LVCF_FMT|LVCF_IMAGE|LVCFMT_COL_HAS_IMAGES;
	GetColumn(nIndex,&lvc);

	if(nIconId < 0)
	{
		//不显示图标
		lvc.mask = LVCF_FMT|LVCF_IMAGE;
		lvc.fmt &= ~(LVCFMT_BITMAP_ON_RIGHT|LVCFMT_IMAGE);
	}
	else
	{
		if(bOnRight)
			lvc.fmt |= LVCFMT_BITMAP_ON_RIGHT|LVCFMT_IMAGE;
		else
			lvc.fmt |= LVCFMT_IMAGE;
	}
	lvc.iImage = nIconId;
	return SetColumn(nIndex,&lvc);
}

int RingListView::AddColumnIcon(int nIconId,HINSTANCE hInst)
{
	if(GetHeaderObj())
		return m_header->AddIcon(nIconId,hInst);
	else
		return -1;
}

int RingListView::AddColumnIcon(HICON hIcon)
{
	if(GetHeaderObj())
		return m_header->AddIcon(hIcon);
	else
		return -1;
}

//显示/隐藏列,iCol为全部列显示状态下的序号
BOOL RingListView::ShowColumn(int iCol,BOOL bShow)
{
	if(GetHeaderObj())
	{
		int nWidth = m_header->ShowColumn(iCol,bShow);
		if(!bShow)
			nWidth = 0;
		BOOL bRes = SetColumnWidth(iCol,nWidth);
		InvalidateRect(m_hWnd,NULL,TRUE);
	}
	return FALSE;
}

//允许在列头右击弹出菜单选择显示/隐藏列
RingCoolMenu* RingListView::EnableColumnMenu(BOOL bEnable)
{
	if(GetHeaderObj())
		return m_header->EnableColumnMenu(bEnable); 
	else
		return NULL;
}

int RingListView::GetCurSel(int nIndex)
{
	int nCnt = GetCount();
	for(int i=nIndex;i<nCnt;i++)
	{
		if(IsSelected(i))
			return i;
	}
	return -1;
}